package servlets;

import ru.ipo.dces.exceptions.GeneralRequestFailureException;
import ru.ipo.dces.exceptions.ServerReturnedError;
import ru.ipo.dces.utils.FileSystemUtils;
import ru.ipo.problemsapi.ExtendedProblem;
import ru.ipo.problemsapi.ZipProblem;
import utils.DummyPHPServer;
import utils.LoggerFactory;
import utils.ReadWriteObject;
import ru.ipo.dces.clientservercommunication.*;
import ru.ipo.dces.server.ServerFacade;
import ru.ipo.dces.server.http.*;

import javax.servlet.ServletException;
import javax.servlet.http.*;
import java.io.*;
import java.util.logging.Logger;

public class UpdateContestServlet extends HttpServlet {

    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws IOException, ServletException {

        Logger logger = LoggerFactory.getLoggerForServlet(this);

        OutputStream out = response.getOutputStream();
        InputStream is = request.getInputStream();
        try {
            UpdateContestDataRequest unserializedReq =
                    ReadWriteObject.readRequest(UpdateContestDataRequest.class, is);
            GetContestDataRequest contestDataRequest = new GetContestDataRequest();
            contestDataRequest.contestID = unserializedReq.contestID;
            contestDataRequest.infoType = GetContestDataRequest.InformationType.AdminInfo;
            contestDataRequest.extendedData = null;
            contestDataRequest.sessionID = "admin_session"; // does not matter with DummyPHPServer
            logger.info("test");

            ServerFacade dummyPHPServer = new DummyPHPServer(this);
            GetContestDataResponse contestDataResponse = dummyPHPServer.doRequest(contestDataRequest);

            logger.info(contestDataResponse.toString());
            if (contestDataResponse.problems != null)
                downloadProblems(contestDataResponse.problems);

            ReadWriteObject.writeResponse(new AcceptedResponse(), out);
        } catch (Exception e) {
            logger.info(e.getMessage());
            RequestFailedResponse failedResponse = new RequestFailedResponse();
            failedResponse.failReason = RequestFailedResponse.FailReason.BrokenServerError;
            failedResponse.extendedInfo = e.getMessage();
            try {
                PHP.serialize(failedResponse, out);
            } catch (IllegalAccessException ignored) {
                logger.info(ignored.getMessage());
            }
        }
        out.flush();
    }

    private void downloadProblems(ProblemDescription[] problemDescriptions) throws Exception {
        String problemsDirPath = getServletConfig().getInitParameter("problems-dir");
        if (problemsDirPath == null)
            return;

        for (ProblemDescription problemDescription : problemDescriptions) {
            String problemsName = new ExtendedProblem(new ZipProblem(problemDescription.problem)).getName();
            if (problemsName == null)
                throw new Exception("Plugin's zip file does not have \"name\" resource");

            File problemsDir = new File(problemsDirPath);
            if (!problemsDir.isAbsolute())
                problemsDir = new File(getServletContext().getRealPath("/") + "/" + problemsDirPath);

            if (!problemsDir.exists())
                problemsDir.mkdirs();

            File problemsFile = new File(problemsDir.getAbsolutePath(), problemsName + ".zip");
            if (!FileSystemUtils.saveBytesToFile(problemDescription.problem, problemsFile))
                throw new IOException("Writing bytes to the zip file has failed");

            String clientPlugin = new ExtendedProblem(new ZipProblem(problemsFile)).getServerPlugin();
            if (clientPlugin != null)
                downloadPlugin(clientPlugin);
        }
    }

    private void downloadPlugin(String pluginName) throws GeneralRequestFailureException, ServerReturnedError, IOException {
        DownloadPluginRequest request = new DownloadPluginRequest();
        request.pluginAlias = pluginName;
        request.side = PluginSide.Client;
        request.sessionID = "admin_session"; // does not matter with DummyPHPServer

        ServerFacade dummyPHPServer = new DummyPHPServer(this);
        DownloadPluginResponse response = dummyPHPServer.doRequest(request);
        if (response.pluginBytes == null)
            return;

        String pluginsDirPath = getServletConfig().getInitParameter("plugins-dir");
        if (pluginsDirPath == null)
            return;

        File pluginsDir = new File(pluginsDirPath);
        if (!pluginsDir.isAbsolute())
            pluginsDir = new File(getServletContext().getRealPath("/") + "/" + pluginsDirPath);

        if (!pluginsDir.exists())
            pluginsDir.mkdirs();

        File pluginsFile = new File(pluginsDir.getAbsolutePath(), pluginName + ".jar");
        if (!FileSystemUtils.saveBytesToFile(response.pluginBytes, pluginsFile))
                throw new IOException("Writing bytes to the jar file has failed");
    }
}